package com.codeoss.framework.view.util;

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.codeoss.framework.context.YunContext;
import com.codeoss.framework.data.metadata.Column;
import com.codeoss.framework.data.metadata.Table;
import com.codeoss.framework.data.store.ITableStore;
import com.codeoss.framework.expression.Expression;
import com.codeoss.framework.expression.IScriptServiceStore;
import com.codeoss.framework.view.datasource.IDataSource;
import com.codeoss.framework.view.datasource.store.IDataSourceStore;

@Component
public class TableCRUDRuleUtil {
	public static final String TABLE_CURD_BEFORE_INSERT="before_insert";
	public static final String TABLE_CURD_BEFORE_UPDATE="before_update";
	public static final String TABLE_CURD_BEFORE_DELETE="before_delete";
	public static final String TABLE_CURD_AFTER_INSERT="after_insert";
	public static final String TABLE_CURD_AFTER_UPDATE="after_update";
	public static final String TABLE_CURD_AFTER_DELETE="after_delete";
	
	@Autowired
	private IScriptServiceStore scriptServiceStore;
	@Autowired
	private IDataSourceStore dataSourceStore;
	@Autowired
	private ITableStore tableStore;
	
	public void doRule(YunContext yunContext,Table table, Map<String, Object> dataMap,String ruleType) {
		if(TABLE_CURD_BEFORE_INSERT.equals(ruleType)) {
			Expression expression=table.getTableCRUDRule().getBeforeInsertExpression();
			if(expression==null) {
				return;
			}
			
			Map<String,Object> bindingMap=createBindingMap(yunContext, table, dataMap);
			scriptServiceStore.getScriptService(expression).eval(expression.getScript(), bindingMap);
		}else if(TABLE_CURD_BEFORE_UPDATE.equals(ruleType)) {
			Expression expression=table.getTableCRUDRule().getBeforeUpdateExpression();
			if(expression==null) {
				return;
			}
			
			Map<String,Object> bindingMap=createBindingMap(yunContext, table, dataMap);
			scriptServiceStore.getScriptService(expression).eval(expression.getScript(), bindingMap);
		}else if(TABLE_CURD_BEFORE_DELETE.equals(ruleType)) {
			Expression expression=table.getTableCRUDRule().getBeforeDeleteExpression();
			if(expression==null) {
				return;
			}
			
			Map<String,Object> bindingMap=createBindingMap(yunContext, table, dataMap);
			scriptServiceStore.getScriptService(expression).eval(expression.getScript(), bindingMap);
		}else if(TABLE_CURD_AFTER_INSERT.equals(ruleType)) {
			Expression expression=table.getTableCRUDRule().getAfterInsertExpression();
			if(expression==null) {
				return;
			}
			
			Map<String,Object> bindingMap=createBindingMap(yunContext, table, dataMap);
			scriptServiceStore.getScriptService(expression).eval(expression.getScript(), bindingMap);
		}else if(TABLE_CURD_AFTER_UPDATE.equals(ruleType)) {
			Expression expression=table.getTableCRUDRule().getAfterUpdateExpression();
			if(expression==null) {
				return;
			}
			
			Map<String,Object> bindingMap=createBindingMap(yunContext, table, dataMap);
			scriptServiceStore.getScriptService(expression).eval(expression.getScript(), bindingMap);
		}else if(TABLE_CURD_AFTER_DELETE.equals(ruleType)) {
			Expression expression=table.getTableCRUDRule().getAfterDeleteExpression();
			if(expression==null) {
				return;
			}
			
			Map<String,Object> bindingMap=createBindingMap(yunContext, table, dataMap);
			scriptServiceStore.getScriptService(expression).eval(expression.getScript(), bindingMap);
		}
	}
	
	private Map<String,Object> createBindingMap(YunContext yunContext,Table table, Map<String, Object> dataMap){
		Map<String,Object> bindingMap=new HashMap<String,Object>();
		bindingMap.putAll(dataMap);
		
		TableCRUDRuleContext tableCRUDRuleContext=new TableCRUDRuleContext();
		tableCRUDRuleContext.setYunContext(yunContext);
		tableCRUDRuleContext.setDataMap(dataMap);
		tableCRUDRuleContext.setTable(table);
		tableCRUDRuleContext.setDataSource(dataSourceStore.getDataSource(table.getAccessType()));
		
		Column parentColumn=table.getParentColumn();
		if(parentColumn!=null) {
			Table parentTable=tableStore.get(parentColumn.getLookupInfo().getDataSourceConfig().getTableName());
			IDataSource parentDataSource=dataSourceStore.getDataSource(parentTable.getAccessType());
			tableCRUDRuleContext.setParentTable(parentTable);
			tableCRUDRuleContext.setParentDataSource(parentDataSource);
		}
		bindingMap.put("tableCRUDRuleContext", tableCRUDRuleContext);
		return bindingMap;
	}
	
	public String doSelectRule(YunContext yunContext,Table table,String action) {
		if(!"select".equals(action)) {
			return null;
		}
		Expression expression=table.getTableCRUDRule().getSelectExpression();
		if(expression!=null) {
			Map<String,Object> bindingMap=createBindingMap(yunContext, table, new HashMap<>());
			String whereClause=(String)scriptServiceStore.getScriptService(expression).eval(expression.getScript(), bindingMap);
			return whereClause;
		}
		return null;
	}
}
